<?php

namespace aszx0413\yii2gii\commands;

use aszx0413\yii2gii\falcon\View;
use aszx0413\yii2gii\Field;
use aszx0413\yii2gii\Many;
use aszx0413\yii2gii\mineadmin\Column;
use aszx0413\yii2gii\Model;
use aszx0413\yii2gii\Sql;
use aszx0413\yii2gii\Table;
use PhpOffice\PhpSpreadsheet\IOFactory;
use Yii;

global $_tables;

class Mygii extends \yii\console\Controller
{
	/**
	 * @var string Excel文件绝对路径
	 */
	protected $excelFile = '';

	/**
	 * @var Table[]
	 */
	private $tables = [];

	public $hasMany = [];

	/**
	 * @var string[] 需要执行的操作
	 */
	protected $runActions = [
		'sql',
		'models',
		'falcon',
	];

	/**
	 * 运行配置
	 * @var array
	 */
	protected $config = [
		// 是否生成SQL脚本
		'sql'    => [],

		// 是否生成Model
		'models' => [],

		// 是否生成falcon模板
		'falcon' => [],
	];

	/**
	 * @var string Models' parent class
	 */
	protected $extendClass = '\aszx0413\yii2gii\models\AR';

	public function actionAll()
	{
		$this->parseExcel();

		if (key_exists('sql', $this->config)) {
			$this->generateSQL();
		}

		if (key_exists('models', $this->config)) {
			$this->generateModels($this->config['models']);
		}

		if (key_exists('falcon', $this->config)) {
			$this->generateFalcon();
		}

		$this->generateMineadmin();
	}

	private function parseExcel()
	{
		if ($this->excelFile == '') {
			$this->excelFile = Yii::$app->basePath . '/db.xlsx';
		} else {
			$this->excelFile = Yii::$app->basePath . '/' . $this->excelFile;
		}

		$spreadsheet = IOFactory::load($this->excelFile);
		$sheet       = $spreadsheet->getActiveSheet();
		$cntRow      = $sheet->getHighestDataRow();

		/* @var Table[] $tables */
		$tables = [];
		/* @var Many[] $hasManyList */
		$hasManyList = [];

		// 分析Excel时先暂存hasMany
		$hasMany = [];

		for ($rowIdx = 1; $rowIdx <= $cntRow; $rowIdx++) {
			// table start
			if ($sheet->getCell('B' . $rowIdx)
					->getValue() == 'TABLE') {
				$table = new Table();

				$table->setName($sheet->getCell('C' . $rowIdx)
					                ->getValue());
				$table->nameCn = $sheet->getCell('D' . $rowIdx)
					->getValue();
				$table->isList = !str_contains($sheet->getCell('I' . $rowIdx)
					                               ->getValue(), '0');
				$table->isForm = !str_contains($sheet->getCell('J' . $rowIdx)
					                               ->getValue(), '0');

				// skip the header rows
				$rowIdx += 2;

				// loop fields rows
				for (; $rowIdx <= $cntRow; $rowIdx++) {
					if ($sheet->getCell('B' . $rowIdx)
							->getValue() == '') { // table end
						$tables[$table->name] = $table;
						break;
					} else { // table field
						$field        = new Field();
						$field->table = $table;

						$field->name    = $sheet->getCell('B' . $rowIdx)
							->getValue();
						$field->nameCn  = $sheet->getCell('C' . $rowIdx)
							->getValue();
						$field->type    = $sheet->getCell('D' . $rowIdx)
							->getValue();
						$field->length  = $sheet->getCell('E' . $rowIdx)
							->getValue();
						$field->key     = $sheet->getCell('F' . $rowIdx)
							->getValue();
						$field->comment = $sheet->getCell('G' . $rowIdx)
							->getValue();

						// 以下是额外配置
						$field->enum = $sheet->getCell('H' . $rowIdx)
							->getValue();
						$field->list = $sheet->getCell('I' . $rowIdx)
							->getValue();
						$field->form = $sheet->getCell('J' . $rowIdx)
							->getValue();

						$cfg        = $sheet->getCell('H' . $rowIdx)->getValue();
						$field->cfg = Field::parseCfg($cfg);

						// 如果字段为 @xxxxx 则表示有关联
						if (str_starts_with($field->nameCn, '@')) {
							$relateTable   = str_replace('@', '', $field->nameCn);
							$field->hasOne = $relateTable;
						}
						if (($many = $field->isHasMany()) !== false) {
							$hasManyList[] = $many;
						}

						$table->fields[] = $field;
					}
				}
			}
		}

		foreach ($hasManyList as $v) {
			$tables[$v->belongTableName]->hasManyList[] = $v;
		}

		$this->tables = $tables;

		global $_tables;
		$_tables = $tables;
	}

	private function generateSQL()
	{
		$content = '';

		foreach ($this->tables as $table) {
			$singleTableContent = Sql::common1($table);

			// loop cols
			foreach ($table->fields as $field) {
				$singleTableContent .= Sql::field($field);
			}

			$singleTableContent .= Sql::common2($table);

			$content .= $singleTableContent;
		}

		file_put_contents(Yii::$app->basePath . '/db.sql', $content);
	}

	/**
	 * 生成Model
	 * @param array $includes 需要执行的表。为空则表示全执行
	 * @return void
	 */
	private function generateModels($includes)
	{
		$model = new Model();
		foreach ($this->tables as $table) {
			if (empty($includes) || in_array($table->name, $includes)) {
				$model->generate($table, $this->tables, ['extendClass' => $this->extendClass]);
			}
		}
	}

	private function generateFalcon()
	{
		foreach ($this->tables as $tb) {
			View::generateList($tb);
			View::generateEdit($tb);
		}
	}

	private function generateMineadmin()
	{
		foreach ($this->tables as $tb) {
			Column::generate($tb);
		}
	}
}